window.onload = (event) => {
    // console.log(event);
    main();
}

function main() {
    const canvas = document.getElementById("canvas");
    const undo = document.querySelector("#undo");
    const redo = document.querySelector("#redo");

    // 设置画布的宽高
    canvas.width = 400;
    canvas.height = 400;

    // 禁用撤销与重做按钮
    undo.disabled = true;
    redo.disabled = true;

    const ctx = canvas.getContext("2d");

    if (!ctx) return;

    const undoHistory = [];
    const redoHistory = [];

    const MOUSE_LEFT_BUTTON = 0; // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button

    let isDrawing = false;
    let x = 0;
    let y = 0;

    // 鼠标按下事件
    canvas.addEventListener("mousedown", (event) => {
        // console.log(event);

        if (event.button !== MOUSE_LEFT_BUTTON) {
            return;
        }

        {
            // 保存画布的像素数据
            const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            const compressed = pako.deflate(new Uint8Array(imageData.data)); // 压缩，减小存储开销
            undoHistory.push(compressed);

            redoHistory.splice(0, redoHistory.length); // 删除所有内容

            undo.disabled = false;
            redo.disabled = true;
        }

        {
            // 保存鼠标在画布中的坐标
            x = event.layerX;
            y = event.layerY;

            isDrawing = true;
        }
    });

    // 鼠标移动事件
    canvas.addEventListener("mousemove", (event) => {
        // console.log(event);
        // console.log(event.layerX, event.layerY);

        if (event.button !== MOUSE_LEFT_BUTTON) {
            return;
        }

        if (isDrawing) {
            drawLine(ctx, "black", 1, x, y, event.layerX, event.layerY);
            x = event.layerX;
            y = event.layerY;
        }
    });

    // 鼠标松开事件
    canvas.addEventListener("mouseup", (event) => {
        console.log(event);

        if (event.button !== MOUSE_LEFT_BUTTON) {
            return;
        }

        if (isDrawing) {
            drawLine(ctx, x, y, event.layerX, event.layerY);
            x = 0;
            y = 0;
            isDrawing = false;
        }
    });

    undo.onclick = (event) => {
        // console.log(event);

        // 在撤销之前，保存当前画布的像素数据
        {
            const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            const compressed = pako.deflate(new Uint8Array(imageData.data));
            redoHistory.push(compressed);

            redo.disabled = false;
        }

        // 撤销
        {
            const compressed = undoHistory.pop();

            try {
                const decompressed = pako.inflate(compressed); // 解压
                const uint8ClampedArray = new Uint8ClampedArray(decompressed);
                const imageData = new ImageData(uint8ClampedArray, canvas.width, canvas.height);

                ctx.putImageData(imageData, 0, 0);
            } catch (error) {
                console.error(error);
            }

            if (undoHistory.length === 0) {
                undo.disabled = true;
            }
        }
    }

    redo.onclick = (event) => {
        // console.log(event);

        // 在重做之前，保存当前画布的像素数据
        {
            const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            const compressed = pako.deflate(new Uint8Array(imageData.data));
            undoHistory.push(compressed);

            undo.disabled = false;
        }

        // 重做
        {
            const compressed = redoHistory.pop();

            try {
                const decompressed = pako.inflate(compressed);
                const uint8ClampedArray = new Uint8ClampedArray(decompressed);
                const imageData = new ImageData(uint8ClampedArray, canvas.width, canvas.height);

                ctx.putImageData(imageData, 0, 0);
            } catch (error) {
                console.log(error);
            }

            if (redoHistory.length === 0) {
                redo.disabled = true;
            }
        }
    }
}

function drawLine(context, strokeStyle, lineWidth, x0, y0, x1, y1) {
    context.beginPath();
    context.strokeStyle = strokeStyle;
    context.lineWidth = lineWidth;
    context.moveTo(x0, y0);
    context.lineTo(x1, y1);
    context.stroke();
}
